package cn.dengta.webapp.trade.dao;

import java.util.Date;
import java.util.List;

import cn.dengta.common.model.TimeInterval;
import cn.dengta.common.model.VerifyStatus;
import cn.dengta.common.web.Page;
import cn.dengta.webapp.base.dao.BaseDao;
import cn.dengta.webapp.base.util.MybatisUtil;
import cn.dengta.webapp.trade.dto.UserIntegralLogSumDTO;
import cn.dengta.webapp.trade.entity.InviteIntegralLog;
import cn.dengta.webapp.trade.form.UserIntegralLogQuery;
import cn.dengta.webapp.user.entity.User;
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
import me.codeplayer.util.StringUtil;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.jdbc.SQL;

import static cn.dengta.webapp.trade.entity.Agent.*;
import static cn.dengta.webapp.trade.entity.InviteIntegralLog.INVITE_REWARD_ID;
import static cn.dengta.webapp.trade.entity.InviteIntegralLog.TO_USER_ID;

/**
 * 邀请奖励日志表 Mapper 接口
 *
 * @author lgy
 * @since 2022-07-14
 */
public interface InviteIntegralLogDao extends BaseDao<InviteIntegralLog> {

	@Select("SELECT user_id userId, SUM(trade_amount) tradeAmount FROM tr_invite_integral_log" +
			" WHERE add_time BETWEEN #{bt} AND #{et} AND status = 0 AND user_id ${userIds} GROUP BY user_id")
	List<InviteIntegralLog> findInviteIncome(@Param("userIds") String userIds, @Param("bt") Date beginTime, @Param("et") Date endTime);

	@Update("UPDATE tr_invite_integral_log SET status = #{status}, remark = #{remark} WHERE invite_reward_id = #{inviteRewardId} AND status = 0 AND user_id = #{userId}")
	Integer updateInviteIncome(@Param("userId") Long userId, @Param("inviteRewardId") Long inviteRewardId, @Param("status") Integer status, @Param("remark") String remark);

	/**
	 * 关联邀请奖励Id
	 */
	@Update("UPDATE tr_invite_integral_log SET invite_reward_id = #{inviteRewardId} WHERE user_id = #{userId} AND add_time BETWEEN #{bt} AND #{et} AND invite_reward_id IS NULL ")
	Integer updateInviteRewardId(@Param("userId") Long userId, @Param("inviteRewardId") Long inviteRewardId, @Param("bt") Date beginTime, @Param("et") Date endTime);

	/**
	 * 查询指定用户、指定交易时间段、指定交易类型(可变参数)的交易数据
	 */
	@SelectProvider(type = InviteIntegralLogSQL.class, method = "findSumOfInfo")
	List<UserIntegralLogSumDTO> findSumOfInfo(@Param("userIds") Long[] userIds, @Param("interval") TimeInterval addTimeInterval, @Param("groupAttr") String groupAttr, String selectKey, boolean userFromOrTo, boolean forFront);

	@SelectProvider(type = InviteIntegralLogSQL.class, method = "findPageSumOfInfo")
	Page<UserIntegralLogSumDTO> findPageSumOfInfo(Page<InviteIntegralLog> page, @Param("userIds") Long[] userIds, @Param("query") UserIntegralLogQuery query, @Param("interval") TimeInterval addTimeInterval, @Param("groupAttr") String groupAttr, String selectKey, boolean userFromOrTo, boolean forFront);

	class InviteIntegralLogSQL {

		public String findPageSumOfInfo(Page<InviteIntegralLog> page, @Param("userIds") Long[] userIds, @Param("query") UserIntegralLogQuery query, @Param("interval") TimeInterval addTimeInterval, @Param("groupAttr") String groupAttr, String selectKey, boolean userFromOrTo, boolean forFront) {
			return sumOfInfo(userIds, query, addTimeInterval, groupAttr, selectKey, userFromOrTo, forFront);
		}

		public String findSumOfInfo(@Param("userIds") Long[] userIds, @Param("interval") TimeInterval addTimeInterval, @Param("groupAttr") String groupAttr, String selectKey, boolean userFromOrTo, boolean forFront) {
			return sumOfInfo(userIds, null, addTimeInterval, groupAttr, selectKey, userFromOrTo, forFront);
		}

		public String sumOfInfo(Long[] userIds, UserIntegralLogQuery query, TimeInterval addTimeInterval, String groupAttr, String selectKey, boolean userFromOrTo, boolean forFront) {
			final String prefix = "log.";
			StringBuilder sb = new StringBuilder(600).append("log.user_id userId, log.coin_trade_type coinTradeType, COUNT(DISTINCT(log.user_id)) userCount, COUNT(log.coin_trade_type) coinTypeCount, IFNULL(SUM(log.trade_amount),0) totalTradeAmount, IFNULL(SUM(log.total_amount),0) totalAmount, SUM(IF(log.coin_trade_type = 'COIN_RECHARGE', log.total_amount, 0)) rechargeAmount")
					.append(", SUM(IF(log.coin_trade_type = 'COIN_FOR_GREET', log.trade_amount, 0)) greetIntegral, SUM(IF(log.coin_trade_type = 'COIN_FOR_MSG', log.trade_amount, 0)) msgIntegral, SUM(IF(log.coin_trade_type = 'COIN_FOR_AUDIO', log.trade_amount, 0)) audioIntegral")
					.append(", SUM(IF(log.coin_trade_type = 'COIN_FOR_VIDEO', log.trade_amount, 0)) videoIntegral, SUM(IF(log.coin_trade_type = 'COIN_FOR_GIFT', log.trade_amount, 0)) giftIntegral, SUM(IF(log.coin_trade_type = 'COIN_RECHARGE', log.trade_amount, 0)) rechargeIntegral");
			SQL sql = new SQL().SELECT(sb.append(StringUtil.toString(selectKey)).toString()).FROM("tr_invite_integral_log log");
			String userIdStr = prefix + (userFromOrTo ? USER_ID : TO_USER_ID);
			MybatisUtil.appendInIdSql(sql, userIdStr, userIds);
			if (query != null) {
				boolean hasUser = query.getUser() != null;
				if (hasUser) {
					sql.JOIN("dt_user u ON u.id = " + userIdStr);
					MybatisUtil.appendEqSql(sql, "u.id", query.getUserId(), "#{query.userId}");
					MybatisUtil.appendEqSql(sql, "u." + User.AGENT_ID, query.getAgentId(), "#{query.agentId}");
					MybatisUtil.appendSql(sql, "u.nickname", SqlKeyword.LIKE, query.getUserNickname(), StringUtil::notEmpty, "${query.userNickname}");
				}
				MybatisUtil.appendEqSql(sql, prefix + INVITE_REWARD_ID, query.getInviteRewardId(), "#{query.inviteRewardId}");
			}
			Integer status = forFront ? VerifyStatus.WAIT_VERIFY.value : VerifyStatus.VERIFY_FALSE.getValue();
			MybatisUtil.appendSql(sql, prefix + STATUS, SqlKeyword.GE, status, status.toString());
			MybatisUtil.appendSqlInterval(sql, prefix + ADD_TIME, addTimeInterval, null);
			boolean hasGroupAttr = StringUtil.notEmpty(groupAttr);
			sql.GROUP_BY(hasGroupAttr ? groupAttr : prefix + USER_ID);
			sql.ORDER_BY(hasGroupAttr ? groupAttr + " desc, log.id" : "log.id");
			return sql.toString();
		}

	}

}
